// Otto by the IdeaLab FabLab
// =====================================================
// PRESS-FIT CUBE (FROM SCRATCH) — 6 PLATES (TUNED OFFSETS)
// + CONNECTOR (PRESS-FIT TAB + SCREW HOLE)
// + EXTRA SLOT ON ONE CUBE SIDE (FRONT FACE) FOR CONNECTOR TAB
// =====================================================


// -------------------- GLOBAL SCALE --------------------
param coeff 3/4


// -------------------- MATERIAL & FIT --------------------
param materialThickness0 3
param kerf0 0.20
param clearance0 0.15

param materialThickness (materialThickness0 * coeff)
param kerf (kerf0 * coeff)
param clearance (clearance0 * coeff)

// base press-fit joint width
param slotW_base (materialThickness + clearance - kerf)

// make joints larger if you want
param jointScale 1.4
param slotW (slotW_base * jointScale)

// tab protrusion length in 2D outline
param tabDepth slotW

// safety to keep slots inside
param eps (0.10 * coeff)


// -------------------- OFFSET TUNING --------------------
param tabIn0 0.85
param slotOut0 0.85

param tabIn (tabIn0 * coeff)
param slotOut (slotOut0 * coeff)


// -------------------- CUBE SIZE --------------------
param cubeS0 50
param cubeS (cubeS0 * coeff)

// 2 joints per edge
param jointInset0 14
param jointInset (jointInset0 * coeff)


// -------------------- SCREW HOLE (SG90 HORN STYLE) --------------------
param hornHoleR0 2.3
param hornInset0 18

param hornHoleR (hornHoleR0 * coeff)
param hornInset (hornInset0 * coeff)


// -------------------- LAYOUT --------------------
param baseX0 0
param baseY0 0

param gap0 18
param gap (gap0 * coeff)

param plateStep (cubeS + gap)

param frontX (baseX0 + 0*plateStep)
param backX  (baseX0 + 1*plateStep)
param leftX  (baseX0 + 2*plateStep)
param rightX (baseX0 + 3*plateStep)
param topX   (baseX0 + 4*plateStep)
param botX   (baseX0 + 5*plateStep)

param Y0 baseY0


// -------------------- EDGE HELPERS --------------------
param halfS (cubeS/2)

// slots OUT a bit: reduce inset
param edgeInset (slotW/2 + eps - slotOut)

param Lx (-halfS + edgeInset)
param Rx ( halfS - edgeInset)
param Ty ( halfS - edgeInset)
param By (-halfS + edgeInset)

param p1 ( jointInset)
param p2 (-jointInset)

// tabs IN a bit: reduce protrusion
param tabPush (tabDepth/2 - tabIn)


// =====================================================
// BASE PLATES (SQUARES)
// =====================================================
shape roundedRectangle plate_front_base { position:[frontX, Y0] width:cubeS height:cubeS radius:0 fill:false }
shape roundedRectangle plate_back_base  { position:[backX,  Y0] width:cubeS height:cubeS radius:0 fill:false }
shape roundedRectangle plate_left_base  { position:[leftX,  Y0] width:cubeS height:cubeS radius:0 fill:false }
shape roundedRectangle plate_right_base { position:[rightX, Y0] width:cubeS height:cubeS radius:0 fill:false }
shape roundedRectangle plate_top_base   { position:[topX,   Y0] width:cubeS height:cubeS radius:0 fill:false }
shape roundedRectangle plate_bot_base   { position:[botX,   Y0] width:cubeS height:cubeS radius:0 fill:false }


// =====================================================
// FRONT — SLOTS on LEFT/RIGHT/TOP/BOTTOM (2 per edge)
// + EXTRA CENTER SLOT (for connector tab)  ✅
// =====================================================
shape roundedRectangle front_slot_L1 { position:[frontX + Lx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle front_slot_L2 { position:[frontX + Lx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle front_slot_R1 { position:[frontX + Rx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle front_slot_R2 { position:[frontX + Rx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle front_slot_T1 { position:[frontX + p1, Y0 + Ty] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle front_slot_T2 { position:[frontX + p2, Y0 + Ty] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle front_slot_B1 { position:[frontX + p1, Y0 + By] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle front_slot_B2 { position:[frontX + p2, Y0 + By] width:slotW height:tabDepth rotation:0 fill:false }

// EXTRA slot on one side (front face), for connector tab
shape roundedRectangle front_slot_CONN {
  position:[frontX, Y0]
  width:slotW
  height:slotW
  radius:0
  rotation:0
  fill:false
}

difference cube_front {
  add plate_front_base
  add front_slot_L1 add front_slot_L2
  add front_slot_R1 add front_slot_R2
  add front_slot_T1 add front_slot_T2
  add front_slot_B1 add front_slot_B2
  add front_slot_CONN
}


// =====================================================
// BACK — same as FRONT (WITHOUT center slot)
// =====================================================
shape roundedRectangle back_slot_L1 { position:[backX + Lx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle back_slot_L2 { position:[backX + Lx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle back_slot_R1 { position:[backX + Rx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle back_slot_R2 { position:[backX + Rx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle back_slot_T1 { position:[backX + p1, Y0 + Ty] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle back_slot_T2 { position:[backX + p2, Y0 + Ty] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle back_slot_B1 { position:[backX + p1, Y0 + By] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle back_slot_B2 { position:[backX + p2, Y0 + By] width:slotW height:tabDepth rotation:0 fill:false }

difference cube_back {
  add plate_back_base
  add back_slot_L1 add back_slot_L2
  add back_slot_R1 add back_slot_R2
  add back_slot_T1 add back_slot_T2
  add back_slot_B1 add back_slot_B2
}


// =====================================================
// LEFT — TABS on all edges (2 per edge)
// =====================================================
shape roundedRectangle left_tab_L1 { position:[leftX - halfS - tabPush, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle left_tab_L2 { position:[leftX - halfS - tabPush, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle left_tab_R1 { position:[leftX + halfS + tabPush, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle left_tab_R2 { position:[leftX + halfS + tabPush, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle left_tab_T1 { position:[leftX + p1, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle left_tab_T2 { position:[leftX + p2, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }

shape roundedRectangle left_tab_B1 { position:[leftX + p1, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle left_tab_B2 { position:[leftX + p2, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }

union cube_left {
  add plate_left_base
  add left_tab_L1 add left_tab_L2
  add left_tab_R1 add left_tab_R2
  add left_tab_T1 add left_tab_T2
  add left_tab_B1 add left_tab_B2
}


// =====================================================
// RIGHT — same as LEFT
// =====================================================
shape roundedRectangle right_tab_L1 { position:[rightX - halfS - tabPush, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle right_tab_L2 { position:[rightX - halfS - tabPush, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle right_tab_R1 { position:[rightX + halfS + tabPush, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle right_tab_R2 { position:[rightX + halfS + tabPush, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

shape roundedRectangle right_tab_T1 { position:[rightX + p1, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle right_tab_T2 { position:[rightX + p2, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }

shape roundedRectangle right_tab_B1 { position:[rightX + p1, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle right_tab_B2 { position:[rightX + p2, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }

union cube_right {
  add plate_right_base
  add right_tab_L1 add right_tab_L2
  add right_tab_R1 add right_tab_R2
  add right_tab_T1 add right_tab_T2
  add right_tab_B1 add right_tab_B2
}


// =====================================================
// TOP — SLOTS on left/right edges + TABS on front/back edges
// =====================================================
shape roundedRectangle top_slot_L1 { position:[topX + Lx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle top_slot_L2 { position:[topX + Lx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle top_slot_R1 { position:[topX + Rx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle top_slot_R2 { position:[topX + Rx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

difference cube_top_plate {
  add plate_top_base
  add top_slot_L1 add top_slot_L2
  add top_slot_R1 add top_slot_R2
}

shape roundedRectangle top_tab_F1 { position:[topX + p1, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle top_tab_F2 { position:[topX + p2, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle top_tab_B1 { position:[topX + p1, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle top_tab_B2 { position:[topX + p2, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }

union cube_top {
  add cube_top_plate
  add top_tab_F1 add top_tab_F2
  add top_tab_B1 add top_tab_B2
}


// =====================================================
// BOTTOM — same as TOP
// =====================================================
shape roundedRectangle bot_slot_L1 { position:[botX + Lx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle bot_slot_L2 { position:[botX + Lx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle bot_slot_R1 { position:[botX + Rx, Y0 + p1] width:slotW height:tabDepth rotation:90 fill:false }
shape roundedRectangle bot_slot_R2 { position:[botX + Rx, Y0 + p2] width:slotW height:tabDepth rotation:90 fill:false }

difference cube_bottom_plate {
  add plate_bot_base
  add bot_slot_L1 add bot_slot_L2
  add bot_slot_R1 add bot_slot_R2
}

shape roundedRectangle bot_tab_F1 { position:[botX + p1, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle bot_tab_F2 { position:[botX + p2, Y0 - halfS - tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle bot_tab_B1 { position:[botX + p1, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }
shape roundedRectangle bot_tab_B2 { position:[botX + p2, Y0 + halfS + tabPush] width:slotW height:tabDepth rotation:0 fill:false }

union cube_bottom {
  add cube_bottom_plate
  add bot_tab_F1 add bot_tab_F2
  add bot_tab_B1 add bot_tab_B2
}


// =====================================================
// CONNECTOR — PRESS-FIT TAB + SCREW HOLE
// =====================================================
param connLen0 60
param connW0 18
param connLen (connLen0 * coeff)
param connW   (connW0 * coeff)

// layout: after the cube plates
param connX (baseX0 + 6*plateStep)
param connY Y0

shape roundedRectangle connector_body {
  position:[connX, connY]
  width:connLen
  height:connW
  radius:0
  fill:false
}

shape circle connector_hole {
  position:[connX - connLen/2 + hornInset, connY]
  radius:hornHoleR
  fill:false
}

// tab at RIGHT end, pulled in slightly like cube tabs
shape roundedRectangle connector_tab {
  position:[connX + connLen/2 + tabPush, connY]
  width:slotW
  height:slotW
  radius:0
  fill:false
}

difference connector_plate {
  add connector_body
  add connector_hole
}

union cube_connector {
  add connector_plate
  add connector_tab
}
